package com.pengshun.modules.api.transport.service.impl;

import com.pengshun.modules.api.coal.repository.MerchantRepository;
import com.pengshun.modules.api.coal.repository.UserRepository;
import com.pengshun.modules.api.coal.util.CommonUtil;
import com.pengshun.modules.api.mapper.PsUserInComRecordMapper;
import com.pengshun.modules.api.mapper.TransportMapper;
import com.pengshun.modules.api.order.repository.MerchantOrderRepository;
import com.pengshun.modules.api.order.repository.OrderAllotTransportRepository;
import com.pengshun.modules.api.order.service.dto.IncomeRecordDto;
import com.pengshun.modules.api.order.service.mapstruct.IncomeRecordTodo;
import com.pengshun.modules.api.transport.dto.FreightSettlementDto;
import com.pengshun.modules.api.transport.dto.TransportDto;
import com.pengshun.modules.api.transport.dto.TransportSettlementDto;
import com.pengshun.modules.api.transport.repository.TransportRepository;
import com.pengshun.modules.api.transport.repository.TransportSettlementRepository;
import com.pengshun.modules.api.transport.repository.TransportTakeOrderRepository;
import com.pengshun.modules.api.transport.service.TransportSettlementService;
import com.pengshun.modules.api.transport.service.mapstruct.TransportSettlementTodo;
import com.pengshun.modules.api.user.repository.IncomeRecordRepository;
import com.pengshun.modules.api.user.repository.IncomeRepository;
import com.pengshun.modules.common.BaseResult;
import com.pengshun.modules.common.OrderCommon;
import com.pengshun.modules.common.PagePara;
import com.pengshun.modules.domain.*;
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * @author luoligang
 * @create 2021/3/19
 */
@Service
@RequiredArgsConstructor
public class TransportSettlementServiceImpl implements TransportSettlementService {

    private final OrderAllotTransportRepository orderAllotTransportRepository;

    private final TransportRepository transportRepository;

    private final TransportTakeOrderRepository transportTakeOrderRepository;

    private final TransportMapper transportMapper;

    private final TransportSettlementRepository transportSettlementRepository;

    private final TransportSettlementTodo transportSettlementTodo;

    private final MerchantRepository merchantRepository;

    private final MerchantOrderRepository merchantOrderRepository;

    private final UserRepository userRepository;

    private final IncomeRepository incomeRepository;

    private final IncomeRecordRepository incomeRecordRepository;

    private final IncomeRecordTodo incomeRecordTodo;

    private final MessageSource messageSource;

    private final PsUserInComRecordMapper uirm;

    @Override
    public BaseResult apply(TransportDto para) {
        //根据货运分配id  查询分配订单详情  判断订单状态
        OrderAllotTransport allotTransport = orderAllotTransportRepository.findById(para.getOrderAllotTransportId()).orElseGet(OrderAllotTransport::new);
        if (allotTransport.getStatus() != 3) {
            //未发布状态不能申请
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.err", null, Locale.CHINA));
        }
        //根据货运id查询 货运详情
        Transport transport = transportRepository.findByOrderAllotTransportId(para.getOrderAllotTransportId());
        if (transport==null) {
            //未发布状态不能申请
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.err", null, Locale.CHINA));
        }
        if (transport.getStatus() != 2) {
            //货运未发布不能申请  防止发布后 删除了在操作
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.err", null, Locale.CHINA));
        }
        //查询货运接单表  没人接单 不能申请
        List<TransportTakeOrder> takeOrders = transportTakeOrderRepository.findByTransportId(transport.getId());
        if (takeOrders.size() == 0) {
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.not.err", null, Locale.CHINA));
        }
        //查询接单有无运输

        //根据货运id  是否存在未申请结算的司机
        Integer isNotSettlementUser = transportMapper.findIsNotSettlementUserById(transport.getId());
        if (isNotSettlementUser > 0) {
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.user.err", null, Locale.CHINA));
        }
        //查询是否所有司机费用已经结算  防止运输公司拿钱不给司机结算
        Integer isNotSettlementUserFee = transportMapper.findIsNotSettlementUserFeeById(transport.getId());
        if (isNotSettlementUserFee > 0) {
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.detil.fee.err", null, Locale.CHINA));
        }

        return new BaseResult(0, transport);
    }

    @Override
    public BaseResult find(TransportDto para) {
        //查询分配详情
        OrderAllotTransport allot = orderAllotTransportRepository.findById(para.getOrderAllotTransportId()).orElseGet(OrderAllotTransport::new);
        //根据货运id查询 货运详情
        Transport transport = transportRepository.findByOrderAllotTransportId(para.getOrderAllotTransportId());
        TransportSettlementDto dto=get(transport,allot);
        return new BaseResult(0, dto);
    }

    private TransportSettlementDto get(Transport transport,OrderAllotTransport allot) {
        //查询结算列表
        List<FreightSettlementDto> list = transportMapper.findSettlementById(transport.getId());
        //总矿发数量
        BigDecimal totalMineSendNum = new BigDecimal(0);
        //总实到数量
        BigDecimal totalRealNum = new BigDecimal(0);
        //差异煤款
        BigDecimal diffPrice=new BigDecimal(0);

        for (FreightSettlementDto st : list) {
            diffPrice=diffPrice.add(st.getDiffPrice());
            totalMineSendNum = totalMineSendNum.add(st.getMineSendNum());
            //当实收吨位大于矿发吨位时则以矿发吨位结算，两者取其小
            totalRealNum = totalRealNum.add(st.getRealNum().compareTo(st.getMineSendNum())==1?st.getMineSendNum():st.getRealNum());
        }
        //总运费
        BigDecimal totalFreight = totalRealNum.multiply(allot.getFreight());
        //盈利
        BigDecimal profit = (allot.getFreight().subtract(transport.getFreightPrice())).multiply(totalRealNum);
        TransportSettlementDto dto = new TransportSettlementDto(new BigDecimal(allot.getAllotNumber()), totalMineSendNum, totalRealNum, allot.getFreight(), transport.getFreightPrice(),
                totalFreight, profit, transport.getId(), allot.getOrderId(), allot.getAllotUserId(), allot.getOrderNo(),diffPrice);
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult save(TransportSettlementDto para) throws Exception{
        //todo 暂时不用了
        TransportSettlement settlement = transportSettlementRepository.findByTransportId(para.getTransportId());
        if (settlement != null) {
            //如果申请或则先删除
            transportSettlementRepository.delete(settlement);
        }
        //查询货运详情
        Transport transport=transportRepository.findById(para.getTransportId()).orElseGet(Transport::new);
        //查询分配详情
        OrderAllotTransport allot = orderAllotTransportRepository.findById(transport.getOrderAllotTransportId()).orElseGet(OrderAllotTransport::new);
        TransportSettlementDto dto=get(transport,allot);
        //判断盈利是否一致
        if(dto.getProfit().compareTo(para.getProfit())!=0){
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.save.not.err", null, Locale.CHINA));
        }
        dto.setApplyTime(new Date());
        dto.setStatus(1);
        dto.setRemark(para.getRemark());
        dto.setSettlementNo("PS"+CommonUtil.getFourRandom());
        dto.setUserId(para.getUserId());
        dto.setOrderAllotTransportId(allot.getOrderAllotTransportId());
        transportSettlementRepository.save(transportSettlementTodo.toEntity(dto));
        //更新货源订单分配状态
        allot.setIsApply(1);
        orderAllotTransportRepository.save(allot);
        //更新接单表状态为已完成
        List<TransportTakeOrder> takeOrders=transportTakeOrderRepository.findByTransportId(para.getTransportId());
        if(takeOrders.size()>0){
            for (TransportTakeOrder to : takeOrders) {
                to.setStatus(2);
            }
            transportTakeOrderRepository.saveAll(takeOrders);
        }
        return new BaseResult(0, messageSource.getMessage("apply.success", null, Locale.CHINA));
    }

    @Override
    public BaseResult list(PagePara para) {
        List<TransportSettlementDto> list=transportMapper.findTransportSettlementList(para.getUserId(),para.getStatus(),para.getPage(),para.getSize());
        return new BaseResult(0,list);
    }

    @Override
    public BaseResult merchantList(PagePara para) {
        List<TransportSettlementDto> list=transportMapper.findMerchantSettlementList(para.getUserId(),para.getStatus(),para.getPage(),para.getSize());
        return new BaseResult(0,list);
    }

    @Override
    public BaseResult detil(TransportSettlementDto para) {
        TransportSettlementDto dto=transportSettlementTodo.toDto(transportSettlementRepository.findById(para.getTransportSettlementId()).orElseGet(TransportSettlement::new));
        Transport transport=transportRepository.findById(dto.getTransportId()).orElseGet(Transport::new);
        Merchant merchant=merchantRepository.findByUserId(dto.getSuerUserId());
        dto.setMerchantName(merchant.getName());
        dto.setTransportName(transport.getMerchantName());
        return new BaseResult(0,dto);
    }

    @Override
    public BaseResult back(TransportSettlementDto para) {
        TransportSettlement dto=transportSettlementRepository.findById(para.getTransportSettlementId()).orElseGet(TransportSettlement::new);
        if(dto.getStatus()!=1){
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.back.status.err", null, Locale.CHINA));
        }
        dto.setStatus(2);
        dto.setCasue(para.getCasue());
        dto.setRejectTime(new Date());
        transportSettlementRepository.save(dto);
        return new BaseResult(0,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult sure(TransportSettlementDto para) throws Exception {
        //确认结算
        TransportSettlement dto=transportSettlementRepository.findById(para.getTransportSettlementId()).orElseGet(TransportSettlement::new);
        if(dto.getStatus()!=1){
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.sure.same.err", null, Locale.CHINA));
        }
        //查询订单信息
        MerchantOrder order=merchantOrderRepository.findById(dto.getOrderId()).orElseGet(MerchantOrder::new);
        //查询已结算总金额  判断订单付款运费 和需要结算的金额
        List<TransportSettlement> list=transportSettlementRepository.findByOrderIdAndStatus(order.getOrderId(),3);
        BigDecimal totalFee=new BigDecimal(0);
        for (TransportSettlement st : list) {
            totalFee=totalFee.add(st.getTotalPrice());
        }
        if(order.getTotalFreight().compareTo(totalFee)==-1){
            //说明运费不足
            return new BaseResult(1, messageSource.getMessage("TransportSettlementServiceImpl.sure.price.err", null, Locale.CHINA));
        }
        User user = userRepository.findById(dto.getUserId()).orElseGet(User::new);
        //账单表添加数据
        Merchant merchant= merchantRepository.findById(order.getMerchantId()).orElseGet(Merchant::new);
        IncomeRecordDto record = new IncomeRecordDto(user.getId(),dto.getSettlementNo(), dto.getProfit(),
                OrderCommon.BPAYMENT_TYPE_ONE,OrderCommon.BILL_TYPE_FOUR, dto.getTransportSettlementId(),OrderCommon.PAY_WAY_FIVE,
                "平台结算煤款",1,new Date(),1,merchant.getName(),merchant.getDoorImg(),dto.getTransportId());
        incomeRecordRepository.save(incomeRecordTodo.toEntity(record));
        //更新余额
        Income userIncome = incomeRepository.findByUserId(dto.getUserId());
        BigDecimal userNowBlanace = userIncome.getUsableBlanace().add(dto.getProfit());
        BigDecimal userNowAccountBlanace = userIncome.getAccountBlanace().add(dto.getProfit());
        uirm.updateBlanace(userIncome.getUsableBlanace(), userNowBlanace, dto.getTransportSettlementId(),userIncome.getAccountBlanace(),userNowAccountBlanace);

        //运输结算表更新状态
        dto.setStatus(3);
        dto.setSettleTime(new Date());
        transportSettlementRepository.save(dto);
        return new BaseResult(0,messageSource.getMessage("sure.success", null, Locale.CHINA));
    }
}
